<!-- 输入框组件 含校验 -->
<template>
	<div class="validate-input-container pb-3">
		<!-- 通过 v-bind="$attrs" 接收父组件传递过来的非props属性 -->
		<input class="form-control" :class="{'is-invalid':inputRef.error}" :value="inputRef.val" @input="updateValue" @blur="validDateInput" v-bind="$attrs">
		<span v-if="inputRef.error" class="invalid-feedback">{{inputRef.message}}</span>
	</div>
</template>

<script lang="ts">
import { defineComponent, PropType, reactive, onMounted } from "vue";
import { emitter } from "./ValidateForm.vue";
const emailReg = /^([a-zA-Z0-9]+[_|_|\-|.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|_|.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/;
interface RuleProp {
	type: "required" | "email";
	message: string;
}
export type RulesProp = RuleProp[];
export default defineComponent({
	name: "ValidateInput",
	props: {
		rules: Array as PropType<RulesProp>,
		modelValue: String, // modelValue关键字 获取v-model传过来的值
	},
	inheritAttrs: false, // 不希望组件的根元素继承特性
	setup(props, context) {
		const inputRef = reactive({
			val: props.modelValue || "",
			error: false,
			message: "",
		});
		const updateValue = (e: KeyboardEvent) => {
			const targetValue = (e.target as HTMLInputElement).value; // 拿到输入的值
			inputRef.val = targetValue;
			context.emit("update:modelValue", targetValue); // 对外发送emit事件，update:modelValue关键字,更新v-model值，实现双向绑定
		};
		const validDateInput = () => {
			if (props.rules) {
				const allPassed = props.rules.every((rule) => {
					let passed = true;
					inputRef.message = rule.message;
					// passed 只要有一项是false 就是校验不通过
					switch (rule.type) {
						case "required":
							passed = inputRef.val.trim() != "";
							break;
						case "email":
							passed = emailReg.test(inputRef.val);
							break;
						default:
							break;
					}
					return passed;
				});
				inputRef.error = !allPassed;
				return allPassed;
			}
			return true;
		};
		onMounted(() => {
			// 发送信息 类似于bus.$emit
			emitter.emit("form-item-created", validDateInput);
		});
		return {
			inputRef,
			validDateInput,
			updateValue,
		};
	},
});
</script>

<style>
</style>
